package com.weijianhuawen.wjblog.web.service.impl;

import com.weijianhuawen.wjblog.common.domain.dos.UserDetailDo;
import com.weijianhuawen.wjblog.common.domain.dos.UserDo;
import com.weijianhuawen.wjblog.common.domain.dos.UserRoleDo;
import com.weijianhuawen.wjblog.common.domain.mapper.UserDetailMapper;
import com.weijianhuawen.wjblog.common.domain.mapper.UserMapper;
import com.weijianhuawen.wjblog.common.domain.mapper.UserRoleMapper;
import com.weijianhuawen.wjblog.common.enums.ResponseCodeEnum;
import com.weijianhuawen.wjblog.common.exception.BizException;
import com.weijianhuawen.wjblog.common.utils.Response;
import com.weijianhuawen.wjblog.web.convert.UserConvert;
import com.weijianhuawen.wjblog.web.mode.vo.user.FindUserInformationReqVo;
import com.weijianhuawen.wjblog.web.mode.vo.user.FindUserInformationRspVo;
import com.weijianhuawen.wjblog.web.mode.vo.user.RegisterUserReqVo;
import com.weijianhuawen.wjblog.web.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @version: java version 8
 * @Author: weijianhuawen
 * @description: 用户服务层
 * @date: 2024-12-10 14:24
 */

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Value("${image.default.url}")
    private String defaultImageUrl;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Resource
    private UserMapper userMapper;
    @Resource
    private UserDetailMapper userDetailMapper;
    @Resource
    private UserRoleMapper userRoleMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response registerOrdinaryUser(RegisterUserReqVo vo) {
        // 获取用户相关信息
        String username = vo.getUsername();
        // 查询用户是否已经存在
        UserDo user = userMapper.findByUsername(username);
        if (Objects.nonNull(user)) {
            // 用户已存在
            throw new BizException(ResponseCodeEnum.USER_ALREADY_EXIST);
        }
        String nickname = vo.getNickname();
        if (!StringUtils.isNotBlank(nickname)) {
            // 昵称为空，自动设置为用户名
            nickname = username;
            vo.setNickname(nickname);
        }
        String mail = vo.getMail();
        String password = vo.getPassword();
        // 密码加密
        String encodePassword = passwordEncoder.encode(password);
        String qqId = vo.getQqId();
        String phoneNumber = vo.getPhoneNumber();
        String avatar = vo.getAvatar();
        if (StringUtils.isBlank(avatar)) {
            avatar = defaultImageUrl;
            vo.setAvatar(avatar);
        }
        Integer sex = vo.getSex();
        if (sex == null || (sex < 0 || sex > 2)) {
            sex = 2;
            vo.setSex(sex);
        }
        LocalDate birthday = vo.getBirthday();
        if (Objects.isNull(birthday)) {
            birthday = LocalDate.now();
            vo.setBirthday(birthday);
        }
        String signature = vo.getSignature();
        if (StringUtils.isBlank(signature)) {
            signature = "该用户很懒，还没有设置个性签名哟！";
            vo.setSignature(signature);
        }
        String introduce = vo.getIntroduce();
        if (StringUtils.isBlank(introduce)) {
            introduce = "该用户很懒，还没有做自我介绍哦！";
            vo.setIntroduce(introduce);
        }
        String localCity = vo.getLocalCity();
        String university = vo.getUniversity();

        // 检查用户的邮箱，qq号，手机号信息，仅能绑定一个平台用户信息
        UserDetailDo userDetail = userDetailMapper.selectUserByMailOrPhoneOrQQ(mail, phoneNumber, qqId);
        if (Objects.nonNull(userDetail)) {
            // qq，邮箱，手机号已被注册
            throw new BizException(ResponseCodeEnum.USER_MAIL_OR_PHONE_OR_QQ_ALREADY_REGISTER);
        }

        // 构建登录用户do
        UserDo userDo = UserDo.builder()
                .username(username)
                .password(encodePassword)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
        // 注册登录用户
        userMapper.insert(userDo);
        // 获取用户id
        Long userId = userDo.getId();
        // 构建用户信息do
        UserDetailDo userDetailDo = UserConvert.INSTANCE.vo2UserDetailDo(vo);
        userDetailDo.setUserId(userId);
        userDetailDo.setIsAdmin(false);
        userDetailDo.setUpdateTime(LocalDateTime.now());
        userDetailDo.setCreateTime(LocalDateTime.now());
        // 注册用户信息
        userDetailMapper.insert(userDetailDo);

        // 添加用户角色
        UserRoleDo userRoleDo = UserRoleDo.builder()
                .role("ROLE_VISITOR")
                .createTime(LocalDateTime.now())
                .username(username)
                .build();
        // 注册用户角色
        userRoleMapper.insert(userRoleDo);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response findUserInformation(FindUserInformationReqVo vo) {
        // 获取用户id
        Long userId = vo.getUserId();
        // 查询用户名
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) {
            // 查询不到结果
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 查询用户信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) {
            // 存在账户，但为兼容迭代老版本，为未初始化用户信息的用户创建基本的用户信息
            autoGenerateUserDetail(userId, userDo.getUsername());
            userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        }
        // 构建数据
        FindUserInformationRspVo rspVo = UserConvert.INSTANCE.userDetailDo2InfoVo(userDetailDo);
        rspVo.setUsername(userDo.getUsername());
        // 处理手机号
        String isolatePhone = isolateDigits(userDetailDo.getPhoneNumber());
        rspVo.setPhoneNumber(isolatePhone);
        // 处理qq号
        String isolateQQ = isolateDigits(userDetailDo.getQqId());
        rspVo.setQqId(isolateQQ);
        // 返回数据
        return Response.success(rspVo);
    }

    // 屏蔽数字
    private String isolateDigits(String digits) {
        if (StringUtils.isBlank(digits)) return "";
        // 获取手机号或qq号或其他id字符串长度
        int size = digits.length();
        StringBuilder stringBuilder = new StringBuilder(size);
        // 长度在11位以及以上，保留前两位，后四位
        if (size >= 11) {
            stringBuilder.append(digits, 0, 2);
            for (int i = 0; i < size - 6; i ++) stringBuilder.append("*");
            stringBuilder.append(digits, size - 4, size);
        } else if (size >= 5) {
            // 长度在5-10位，保留前一位，后俩位
            stringBuilder.append(digits, 0, 1);
            for (int i = 0; i < size - 3; i ++) stringBuilder.append("*");
            stringBuilder.append(digits, size - 2, size);
        } else {
            // 长度小于5位，不保留任何信息
            for (int i = 0; i < size; i ++) stringBuilder.append("*");
        }
        return stringBuilder.toString();
    }

    private void autoGenerateUserDetail(Long userId, String username) {
        // 生成UUID
        String uuidStr = UUID.randomUUID().toString();
        String mail = "请尽快设置邮箱！" + uuidStr;
        // 设置默认头像
        String avatar = defaultImageUrl;
        // 设置签名
        String signature = "该用户很懒，还没有设置个性签名哟！";
        // 查找用户角色表
        List<UserRoleDo> userRoleDos = userRoleMapper.selectUserRoleByUsername(username);
        Boolean isAdmin = false;
        // 遍历用户角色
        if (!CollectionUtils.isEmpty(userRoleDos)) {
            for (UserRoleDo userRoleDo : userRoleDos) {
                if (Objects.equals("ROLE_ADMIN", userRoleDo.getRole())) {
                    isAdmin = true;
                    break;
                }
            }
        }
        // 其他按照数据库默认值
        // 构建do
        UserDetailDo userDetailDo = UserDetailDo.builder()
                .userId(userId)
                .nickname(username)
                .avatar(avatar)
                .mail(mail)
                .signature(signature)
                .isAdmin(isAdmin)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .birthday(LocalDate.now())
                .build();

        // 保存
        userDetailMapper.insert(userDetailDo);
    }
}
